package leetcode.sword;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class Solution20 {

    public static void main(String[] args) {
        System.out.println(new Solution20().isNumber("1."));
    }

    public boolean isNumber(String s) {
        //状态转移路径
        Map<State,Map<CharType,State>> transfer = new HashMap<>();
        //初始状态的转移路径
        Map<CharType,State> initMap = new HashMap<CharType,State>(){{
            put(CharType.CHAR_SPACE, State.STATE_INIT);
            put(CharType.CHAR_NUMBER,State.STATE_INTEGER);
            put(CharType.CHAR_POINT,State.STATE_POINT_WITHOUT_INT);
            put(CharType.CHAR_SIGN,State.STATE_INT_SIGN);
        }};
        transfer.put(State.STATE_INIT,initMap);
        //整数部分正负号状态的转移路径
        Map<CharType, State> intSignMap = new HashMap<CharType, State>() {{
            put(CharType.CHAR_NUMBER, State.STATE_INTEGER);
            put(CharType.CHAR_POINT, State.STATE_POINT_WITHOUT_INT);
        }};
        transfer.put(State.STATE_INT_SIGN, intSignMap);
        //整数部分状态的转移路径
        Map<CharType, State> integerMap = new HashMap<CharType, State>() {{
            put(CharType.CHAR_NUMBER, State.STATE_INTEGER);
            put(CharType.CHAR_EXP, State.STATE_EXP);
            put(CharType.CHAR_POINT, State.STATE_POINT);
            put(CharType.CHAR_SPACE, State.STATE_END);
        }};
        transfer.put(State.STATE_INTEGER, integerMap);
        //小数点状态的转移路径
        Map<CharType, State> pointMap = new HashMap<CharType, State>() {{
            put(CharType.CHAR_NUMBER, State.STATE_FRACTION);
            put(CharType.CHAR_EXP, State.STATE_EXP);
            put(CharType.CHAR_SPACE, State.STATE_END);
        }};
        transfer.put(State.STATE_POINT, pointMap);
        //无整数部分小数点状态的转移路径
        Map<CharType, State> pointWithoutIntMap = new HashMap<CharType, State>() {{
            put(CharType.CHAR_NUMBER, State.STATE_FRACTION);
        }};
        transfer.put(State.STATE_POINT_WITHOUT_INT, pointWithoutIntMap);
        //小数点部分转移路径
        Map<CharType, State> fractionMap = new HashMap<CharType, State>() {{
            put(CharType.CHAR_NUMBER, State.STATE_FRACTION);
            put(CharType.CHAR_EXP, State.STATE_EXP);
            put(CharType.CHAR_SPACE, State.STATE_END);
        }};
        transfer.put(State.STATE_FRACTION, fractionMap);
        //指数符号状态转移路径
        Map<CharType, State> expMap = new HashMap<CharType, State>() {{
            put(CharType.CHAR_NUMBER, State.STATE_EXP_NUMBER);
            put(CharType.CHAR_SIGN, State.STATE_EXP_SIGN);
        }};
        transfer.put(State.STATE_EXP, expMap);
        //指数部分正负号状态转移路径
        Map<CharType, State> expSignMap = new HashMap<CharType, State>() {{
            put(CharType.CHAR_NUMBER, State.STATE_EXP_NUMBER);
        }};
        transfer.put(State.STATE_EXP_SIGN, expSignMap);
        //指数部分数字状态转移路径
        Map<CharType, State> expNumberMap = new HashMap<CharType, State>() {{
            put(CharType.CHAR_NUMBER, State.STATE_EXP_NUMBER);
            put(CharType.CHAR_SPACE, State.STATE_END);
        }};
        transfer.put(State.STATE_EXP_NUMBER, expNumberMap);
        //结束状态转移路径
        Map<CharType, State> endMap = new HashMap<CharType, State>() {{
            put(CharType.CHAR_SPACE, State.STATE_END);
        }};
        transfer.put(State.STATE_END, endMap);

        //可接受结束状态
        Set<State> acceptEndState = new HashSet<State>(){{
            add(State.STATE_INTEGER);
            add(State.STATE_POINT);
            add(State.STATE_FRACTION);
            add(State.STATE_EXP_NUMBER);
            add(State.STATE_END);
        }};

        //状态机启动
        int length = s.length();
        State state = State.STATE_INIT;
        for (int i = 0; i < s.length(); i++) {
            CharType type = toCharType(s.charAt(i));
            if(!transfer.get(state).containsKey(type)){ //状态机无此转移路径
                return false;
            }else {
                state = transfer.get(state).get(type);
            }
        }
        return acceptEndState.contains(state);
    }


    //字符类型
    enum CharType {
        CHAR_NUMBER,
        CHAR_EXP,
        CHAR_POINT,
        CHAR_SIGN,
        CHAR_SPACE,
        CHAR_ILLEGAL
    }

    //有限状态
    enum State {
        STATE_INIT,
        STATE_INT_SIGN,
        STATE_INTEGER,
        STATE_POINT,
        STATE_POINT_WITHOUT_INT,
        STATE_FRACTION, //小数部分
        STATE_EXP,
        STATE_EXP_SIGN,
        STATE_EXP_NUMBER,
        STATE_END
    }

    public CharType toCharType(char ch){
        if(ch>='0'&&ch<='9'){
            return CharType.CHAR_NUMBER;
        }else if(ch=='e'||ch=='E'){
            return CharType.CHAR_EXP;
        }else if(ch=='.'){
            return CharType.CHAR_POINT;
        }else if(ch=='+'||ch=='-'){
            return CharType.CHAR_SIGN;
        }else if(ch==' '){
            return CharType.CHAR_SPACE;
        }else {
            return CharType.CHAR_ILLEGAL;
        }
    }

}
